#include "CBuilding.h"

#include "CRegionSceneNode.h"

CBuilding::~CBuilding()
{
}

const matrix4 CBuilding::getAbsoluteTransformation() const
{
	return Block->getAbsoluteTransformation() * getRelativeTransformation();
}

const matrix4 CBuilding::getRelativeTransformation() const
{
	matrix4 mat;
	mat.setRotationDegrees(RelativeRotation);
	mat.setTranslation(RelativeTranslation);

	if(RelativeScale != vector3df(1.f,1.f,1.f))
	{
		matrix4 smat;
		smat.setScale(RelativeScale);
		mat *= smat;
	}
	return mat;
}

#define TILE_NORTH_WEST	1
#define TILE_NORTH_EAST	0
#define	TILE_SOUTH_EAST	3
#define	TILE_SOUTH_WEST	2

#define	TILE_NORTH		1
#define	TILE_EAST		0
#define	TILE_SOUTH		3
#define	TILE_WEST		2

#define TILE_WALL(_a)	(_a ? DFHack::isWallTerrain(_a->TileType) : false)
#define TILE_RAMP(_a)	(_a ? DFHack::isRampTerrain(_a->TileType) : false)
#define TILE_FLOOR(_a)	(_a ? DFHack::isFloorTerrain(_a->TileType) : false)
#define TILE_OPEN(_a)	(_a ? DFHack::isOpenTerrain(_a->TileType) : false)

void CBuilding::setBuildingType(u32 buildingtype)
{
	BuildingType = buildingtype;
	std::string name = CSettings::getNameFromBuildingType(buildingtype);
	if(name.compare("") != 0)
		Resource = Block->getRegion()->getResource(name);

	if(Resource)
	{
		CRegionSceneNode *region = Block->getRegion();

		BoundingBox = Resource->Mesh->getBoundingBox();
		Resource->getTransformation().transformBoxEx(BoundingBox);

		TransformedBoundingBox = BoundingBox;
		this->getAbsoluteTransformation().transformBoxEx(TransformedBoundingBox);

		vector3di a = this->getGlobalPosition();
		CTile *adj[] = { 0, 0, 0, 0 };
		CTile *cor[] = { 0, 0, 0, 0 };

		if(Resource->Name.compare("DOOR") == 0)
		{
			adj[TILE_EAST] = region->getTile(a + vector3di(-1, 0, 0));
			adj[TILE_NORTH] = region->getTile(a + vector3di(0, 0, -1));
			adj[TILE_WEST] = region->getTile(a + vector3di(1, 0, 0));
			adj[TILE_SOUTH] = region->getTile(a + vector3di(0, 0, 1));

			if(TILE_WALL(adj[TILE_WEST]) || TILE_WALL(adj[TILE_EAST]))
				Resource = region->getResource("DOOR_NORTH_SOUTH");
		}
		else if(Resource->Name.compare("STATUE") == 0)
		{
			adj[TILE_EAST] = region->getTile(a + vector3di(-1, 0, 0));
			adj[TILE_NORTH] = region->getTile(a + vector3di(0, 0, -1));
			adj[TILE_WEST] = region->getTile(a + vector3di(1, 0, 0));
			adj[TILE_SOUTH] = region->getTile(a + vector3di(0, 0, 1));

			cor[TILE_NORTH_EAST] = region->getTile(a + vector3di(-1,0,-1));
			cor[TILE_NORTH_WEST] = region->getTile(a + vector3di(1,0,-1));
			cor[TILE_SOUTH_WEST] = region->getTile(a + vector3di(1,0,1));
			cor[TILE_SOUTH_EAST] = region->getTile(a + vector3di(-1,0,1));

			if(TILE_WALL(adj[TILE_NORTH]))
			{
				if(TILE_WALL(adj[TILE_SOUTH]))
				{
					if(TILE_WALL(adj[TILE_EAST]))
						Resource = region->getResource("STATUE_WEST");
					else
						Resource = region->getResource("STATUE_EAST");
				}
				else
					Resource = region->getResource("STATUE_SOUTH");
			}
			else if(TILE_WALL(adj[TILE_SOUTH]))
			{
				if(TILE_WALL(adj[TILE_WEST]))
				{
					if(TILE_WALL(adj[TILE_EAST]))
						Resource = region->getResource("STATUE_NORTH");
					else
						Resource = region->getResource("STATUE_EAST");
				}
				else
					Resource = region->getResource("STATUE_NORTH");
			}
			else if(TILE_WALL(adj[TILE_EAST]))
			{
				if(TILE_WALL(adj[TILE_WEST]))
					Resource = region->getResource("STATUE_NORTH");
				else
					Resource = region->getResource("STATUE_WEST");
			}
			else if(TILE_WALL(adj[TILE_WEST]))
			{
				if(TILE_WALL(adj[TILE_EAST]))
					Resource = region->getResource("STATUE_NORTH");
				else
					Resource = region->getResource("STATUE_EAST");
			}
		}
	}
}

SBasicMaterial* CBuilding::getMaterial() const
{
	return Material;
}

const vector3di CBuilding::getGlobalPosition() const
{
	vector3df pos = Block->getPosition();
	return vector3di((s32)(pos.X + RelativeTranslation.X), (s32)(pos.Y + RelativeTranslation.Y), (s32)(pos.Z + RelativeTranslation.Z));
}